package cn.javaxc.mvcwork.controller;
import cn.javaxc.mvcwork.framework.actions.TActionContext;
import cn.javaxc.mvcwork.modules.admin.*;
import cn.javaxc.mvcwork.modules.file.FileItemList;
import cn.javaxc.mvcwork.modules.notifier.Campaign;
import cn.javaxc.model.base.*;
import cn.javaxc.mvcwork.util.helper.FrameHelper;
import cn.javaxc.mvcwork.util.common.SMTPHelper;
import cn.javaxc.mvcwork.util.common.DatabaseUtils;
import cn.javaxc.mvcwork.util.contact.SSLMessage;
import java.sql.*;
import java.util.*;





public class Notification{

  public final static int EMAIL = 1;
  public final static int FAX = 2;
  public final static int LETTER = 3;
  public final static int EMAILFAX = 4;
  public final static int EMAILLETTER = 5;
  public final static int EMAILFAXLETTER = 6;
  public final static int IM = 7;
  public final static int SSL = 8;
  public final static int BROADCAST = 9;

  public final static String EMAIL_TEXT = "Email";
  public final static String FAX_TEXT = "Fax";
  public final static String LETTER_TEXT = "Letter";
  public final static String EMAILFAX_TEXT = "Email first, try Fax";
  public final static String EMAILLETTER_TEXT = "Email first, then Letter";
  public final static String EMAILFAXLETTER_TEXT = "Email first, try Fax, then Letter";
  public final static String IM_TEXT = "Instant Message";
  public final static String SSL_TEXT = "SSL Message";

  public final static String lf = System.getProperty("line.separator");

  String faxLogEntry = null;
  Contact contact = null;

  private int id = -1;
  private String databaseName = null;
  private String emailToNotify = null;
  private int userToNotify = -1;
  private int contactToNotify = -1;
  private String module = null;
  private int itemId = -1;
  private java.sql.Timestamp itemModified = null;
  private String from = null;
  private String subject = null;
  private int messageIdToSend = -1;
  private String messageToSend = null;
  private int type = -1;
  private String typeText = null;

  private String host = "127.0.0.1";
  private int port = -1;

  private String siteCode = null;
  private java.sql.Timestamp attempt = null;
  private int result = 0;
  private String status = "";
  private Exception errorMessage = null;

  private Connection connection = null;
  private Object context = null;

  private FileItemList fileAttachments = null;

  private long size = 0;

  private String bcc = null;
  private String cc = null;
  private int campaignType = -1;
  private String replyMail="";
  private String replyFax="";

  
  public Notification() {
  }


  
  public Notification(ResultSet rs) throws SQLException {
    buildRecord(rs);
  }


  
  public Notification(int thisType) {
    this.setType(thisType);
  }


  
  public Notification(int thisType, TActionContext context) {
    this.setType(thisType);
    this.context = context;
  }


  
  public void setUserToNotify(int tmp) {
    this.userToNotify = tmp;
  }


  
  public void setUserToNotify(String tmp) {
    this.userToNotify = Integer.parseInt(tmp);
  }


  
  public void setItemId(String tmp) {
    this.itemId = Integer.parseInt(tmp);
  }


  
  public void setAttempt(String tmp) {
    this.attempt = DatabaseUtils.parseTimestamp(tmp);
  }


  
  public void setResult(String tmp) {
    this.result = Integer.parseInt(tmp);
  }


  
  public void setContactToNotify(int tmp) {
    this.contactToNotify = tmp;
  }


  
  public void setEmailToNotify(String tmp) {
    this.emailToNotify = tmp;
  }


  
  public void setDatabaseName(String tmp) {
    this.databaseName = tmp;
  }


  
  public void setModule(String tmp) {
    this.module = tmp;
  }


  
  public void setItemId(int tmp) {
    this.itemId = tmp;
  }


  
  public void setItemModified(java.sql.Timestamp tmp) {
    this.itemModified = tmp;
  }


  
  public void setMessageIdToSend(int tmp) {
    this.messageIdToSend = tmp;
  }


  
  public void setMessageToSend(String tmp) {
    this.messageToSend = tmp;
  }


  
  public void setType(int tmp) {
    this.type = tmp;
    switch (this.type) {
      case EMAIL:
        this.setTypeText(EMAIL_TEXT);
        break;
      case FAX:
        this.setTypeText(FAX_TEXT);
        break;
      case LETTER:
        this.setTypeText(LETTER_TEXT);
        break;
      case EMAILFAX:
        this.setTypeText(EMAILFAX_TEXT);
        break;
      case EMAILLETTER:
        this.setTypeText(EMAILLETTER_TEXT);
        break;
      case EMAILFAXLETTER:
        this.setTypeText(EMAILFAXLETTER_TEXT);
        break;
      case IM:
        this.setTypeText(IM_TEXT);
        break;
      case SSL:
        this.setTypeText(SSL_TEXT);
        break;
      default:
        break;
    }
  }


  
  public void setTypeText(String tmp) {
    this.typeText = tmp;
  }


  
  public void setSubject(String tmp) {
    this.subject = tmp;
  }


  
  public void setFrom(String tmp) {
    this.from = tmp;
  }


  
  public void setSiteCode(String tmp) {
    this.siteCode = tmp;
  }


  
  public void setPort(int tmp) {
    this.port = tmp;
  }


  
  public void setHost(String tmp) {
    this.host = tmp;
  }


  
  public void setStatus(String tmp) {
    this.status = tmp;
  }


  
  public void setFileAttachments(FileItemList tmp) {
    this.fileAttachments = tmp;
  }


  
  public void setContext(Object context) {
    this.context = context;
  }


  
  public java.sql.Timestamp getAttempt() {
    return attempt;
  }


  
  public int getResult() {
    return result;
  }


  
  public String getStatus() {
    return status;
  }


  
  public int getType() {
    return type;
  }


  
  public Exception getErrorMessage() {
    return errorMessage;
  }


  
  public String getFaxLogEntry() {
    return faxLogEntry;
  }


  
  public Contact getContact() {
    return contact;
  }


  
  public FileItemList getFileAttachments() {
    return fileAttachments;
  }


  
  public long getSize() {
    return size;
  }


  
  public int getUserToNotify() {
    return userToNotify;
  }


  
  public String getModule() {
    return module;
  }


  
  public int getItemId() {
    return itemId;
  }


  
  public java.sql.Timestamp getItemModified() {
    return itemModified;
  }


  
  public String getTypeText() {
    return typeText;
  }


  
  public String getSubject() {
    return subject;
  }


  
  public String getMessageToSend() {
    return messageToSend;
  }


  
  public String getBcc() {
    return bcc;
  }


  
  public void setBcc(String tmp) {
    this.bcc = tmp;
  }


  
  public String getCc() {
    return cc;
  }


  
  public void setCc(String tmp) {
    this.cc = tmp;
  }


  
  public void setCampaignType(int tmp) {
    this.campaignType = tmp;
  }


  
  public void setCampaignType(String tmp) {
    this.campaignType = Integer.parseInt(tmp);
  }


  
  public int getCampaignType() {
    return campaignType;
  }

  public int getId() {
    return id;
  }
  
  public boolean isNew(Connection db) {
    int resultCheck = -1;
    try {

      String sql =
          "SELECT * " +
              "FROM notification " +
              "WHERE notify_user = " + ((userToNotify > -1) ? userToNotify : contactToNotify) + " " +
              "AND " + DatabaseUtils.addQuotes(db, "module") + " = ? " +
              "AND item_id = " + itemId + " " +
              "AND item_modified = ? ";

      int i = 0;
      PreparedStatement pst = db.prepareStatement(sql);
      pst.setString(++i, module);
      if (itemModified == null) {
        pst.setNull(++i, java.sql.Types.DATE);
      } else {
        pst.setTimestamp(++i, itemModified);
      }

      ResultSet rs = pst.executeQuery();
      if (rs.next()) {
        resultCheck = 1;
      } else {
        resultCheck = 0;
      }
      rs.close();
      pst.close();

    } catch (SQLException e) {
      errorMessage = e;
      result += 1;
    }

    return (resultCheck == 0);
  }


  
  public boolean hasErrors() {
    return (result > 0);
  }


  
  public void insertNotification(Connection db) {
    try {
      String sql =
          "INSERT INTO notification " +
              "(" + (id > -1 ? "notification_id, " : "") + "notify_user, " + DatabaseUtils.addQuotes(db, "module") +
              ", item_id, item_modified, notify_type, subject, " + DatabaseUtils.addQuotes(db, "message") +
              ", result, errorMessage) " +
              "VALUES " +
              "(" + (id > -1 ? "?, " : "") + "?, ?, ?, ?, ?, ?, ?, ?, ?) ";
      int i = 0;
      PreparedStatement pst = db.prepareStatement(sql);
      if (id > -1) {
        pst.setInt(++i, id);
      }
      if (userToNotify > -1) {
        pst.setInt(++i, userToNotify);
      } else {
        pst.setInt(++i, contactToNotify);
      }
      pst.setString(++i, module);
      pst.setInt(++i, itemId);
      if (itemModified == null) {
        pst.setNull(++i, java.sql.Types.DATE);
      } else {
        pst.setTimestamp(++i, itemModified);
      }
      pst.setString(++i, typeText);
      pst.setString(++i, subject);
      pst.setString(++i, messageToSend);
      pst.setInt(++i, result);
      pst.setString(++i, errorMessage==null?null:String.valueOf(errorMessage));
      pst.executeUpdate();
      pst.close();
      id = DatabaseUtils.getCurrVal(db, "notification_notification_i_seq", id);
    } catch (SQLException e) {
      errorMessage = e;
      result += 1;
    }
  }


  
  public boolean notifyAddress() {
    if (type > -1) {
      try {
        if (type == EMAIL) {
          if (emailToNotify == null || "".equals(emailToNotify.trim())) {
            result = 2;
            return false;
          }
          System.out.println("Notification-> notifyAddress: " + emailToNotify);
          SMTPHelper mail = MVCConfig.getConfig().createSMTPHelper();
          mail.setHost(host);
          mail.setFrom(from);
          if (from != null && !from.equals("")) {
            mail.addReplyTo(from);
          }
          mail.setType("text/html");
          mail.addTo(emailToNotify);
          mail.setSubject(subject);
          mail.setBody(messageToSend);
          mail.setAttachments(fileAttachments);
          if (mail.send() == 2) {
            System.out.println(
                "Send error: " + mail.getErrorMsg() + "<br><br>");
            System.err.println(
                "ReportBuilder Error: Report could not be sent");
            System.err.println(mail.getErrorMsg());
          } else {
            //insertNotification(db);
          }
        } else if (type == IM) {

        } else if (type == FAX) {

        } else if (type == SSL) {

        }
      } catch (Exception e) {
        result = 2;
        errorMessage = e;
        return false;
      }
    } else {
      System.out.println("Notification-> Type not set");
      return false;
    }
    return true;
  }


  
  public void notifyUser(Connection db) {
    if (type > -1) {
      try {
        User thisUser = new User();
        thisUser.setBuildContact(true);
        thisUser.setBuildContactDetails(true);
        thisUser.buildRecord(userToNotify);
        if (type == EMAIL) {
          System.out.println(
              "Notification-> notifyUser: " + thisUser.getContact().getPrimaryEmailAddress());
          SMTPHelper mail = MVCConfig.getConfig().createSMTPHelper();
          mail.setHost(host);
          mail.setFrom(from);
          if (from != null && !from.equals("")) {
            mail.addReplyTo(from);
          }
          mail.setType("text/html");
          mail.addTo(thisUser.getContact().getPrimaryEmailAddress());
          mail.setSubject(subject);
          mail.setBody(messageToSend);
          mail.setAttachments(fileAttachments);
          if (mail.send() == 2) {
            System.out.println(
                "Send error: " + mail.getErrorMsg() + "<br><br>");
            System.err.println(
                "ReportBuilder Error: Report could not be sent");
            System.err.println(mail.getErrorMsg());
          } else {
            insertNotification(db);
          }
        } else if (type == IM) {

        } else if (type == FAX) {

        } else if (type == SSL) {

        }
      } catch (Exception e) {
        result = 2;
        errorMessage = e;
      }
    } else {
      System.out.println("Notification-> Type not set");
    }
  }


  
  public void notifyContact(Connection db) {
    if (type > -1) {
      try {
//        
        //Determine the method...
        if (type == EMAILFAXLETTER) {
          if (("".equals(replyMail)) &&replyFax.equals("") &&replyMail!= null) {
            type = LETTER;
          } else {
            type = EMAILFAX;
          }
        }
        //2nd level
        if (type == EMAILFAX) {
          if (("".equals(replyMail)) &&!replyFax.equals("")) {
            type = FAX;
          } else {
            type = EMAIL;
          }
        } else if (type == EMAILLETTER) {
          if (("".equals(replyMail)) &&replyMail != null) {
            type = LETTER;
          } else {
            type = EMAIL;
          }
        }
        //Send it...
        if (type == EMAIL) {
          if ((campaignType == Campaign.GENERAL) && ("".equals(replyMail))) {
            status = "Email opt out";
          } else {
            System.out.println(
                "Notification-> notifyContact: " + "".equals(replyMail));
            SMTPHelper mail = MVCConfig.getConfig().createSMTPHelper();
            mail.setHost(host);
            mail.setFrom(from);
            if (from != null && !from.equals("")) {
              mail.addReplyTo(from);
            }
            if (bcc != null && !"".equals(bcc)) {
              mail.setBcc(bcc);
            }
            if (cc != null && !"".equals(cc)) {
              mail.setCc(cc);
            }
            mail.setType("text/html");
            mail.addTo(replyMail);
            mail.setSubject(subject);
            mail.setBody(messageToSend);
            mail.setAttachments(fileAttachments);
			int errorCode =0;
			if (mail.getMailTo()== null) {
				SQLList s_user_email = FrameHelper.getBaseSQL().createList();
				s_user_email .setTable("v_user_email");
					
				String sql="select *\n"+
				" from v_user_email t_v_user_email\n"+
				" where 1=1 and user_id=(select enteredby from campaign where campaign_id="+getItemId()+")";

				s_user_email.buildTable(sql);
				errorCode = mail.send(s_user_email.getExistfirst());
			}else{
				errorCode = mail.send();
			}
            if (errorCode > 0) {
              status = "Email Error";
			  errorMessage=mail.getErrorMsg();
            } else {
              status = "Email Sent";
			}
              insertNotification(db);
              size = subject.length() +
                  messageToSend.length() +
                  fileAttachments.getFileSize();
            
          }
        } else if (type == IM) {
          if ((campaignType == Campaign.GENERAL) && ("".equals(replyFax))) {
            status = "IM opt out";
          } else {
            status = "IM Sent";
          }
        } else if (false&&type == BROADCAST) {
			Contact thisContact = new Contact(String.valueOf(contactToNotify));
          SMTPHelper mail = MVCConfig.getConfig().createSMTPHelper();
          mail.setHost(host);
          mail.setFrom(from);
          if (from != null && !from.equals("")) {
            mail.addReplyTo(from);
          }
          mail.setType("text/html");
          boolean canEmail = false;
          //sending to all email addresses
          if (!((campaignType == Campaign.GENERAL) && (thisContact.getNoEmail()))) {
            canEmail = true;
//            Iterator itr = thisContact.getEmailAddressList().iterator();
//            if (itr.hasNext()) {
//              while (itr.hasNext()) {
//                EmailAddress tmpEmailAddress = (EmailAddress) itr.next();
//                mail.addTo(tmpEmailAddress.getEmail());
//              }
//            }
          }
          boolean canPage = true;
          //sending to all text message addresses
//          Iterator itr = thisContact.getTextMessageAddressList().iterator();
//          if (itr.hasNext()) {
//            while (itr.hasNext()) {
//              TextMessageAddress tmpTextMessageAddress = (TextMessageAddress) itr.next();
//              mail.addTo(tmpTextMessageAddress.getTextMessageAddress());
//            }
//          }
          mail.setSubject(subject);
          mail.setBody(messageToSend);
          mail.setAttachments(fileAttachments);
          int errorCode = mail.send();
          if (errorCode > 0) {
            status = "Email Error";
            System.out.println(
                "Send error: " + mail.getErrorMsg() + "<br><br>");
            System.err.println(
                "ReportBuilder Error: Report could not be sent");
            System.err.println(mail.getErrorMsg());
          } else {
            if (canEmail && canPage) {
              status = "Broadcast Sent";
            } else {
              if (!canEmail) {
                status = "Email Opt Out";
              }
              if (!canPage) {
                status = "Text Message Opt Out";
              }
              if ((!canEmail) && (!canPage)) {
                status = "Email and Text Message Opt Out";
              }
            }
            insertNotification(db);
            size = subject.length() +
                messageToSend.length() +
                fileAttachments.getFileSize();
          }
        } else if (type == FAX) {
          String phoneNumber = replyFax;
          System.out.println("Notification-> To: " + phoneNumber);
          if ((campaignType == Campaign.GENERAL) && ("".equals(replyFax))) {
            status = "Fax opt out";
          } else if (!phoneNumber.equals("") && phoneNumber.length() > 0) {
            phoneNumber = convertToNumber(phoneNumber);
            if (phoneNumber.startsWith("1")) {
              phoneNumber = phoneNumber.substring(1);
            }
            if (phoneNumber.startsWith("757")) {
              phoneNumber = phoneNumber.substring(3);
            } else {
              phoneNumber = "1" + phoneNumber;
            }
            System.out.println(
                "Notification-> Will send fax to: " + phoneNumber);
            faxLogEntry = databaseName + "|" + messageIdToSend + "|" + phoneNumber + "|" + contactToNotify;
            status = "Fax Queued";
          }
        } else if (type == LETTER) {
          if (!((campaignType == Campaign.GENERAL) && ("".equals(replyMail)))) {
            status = "Added to Report";
          } else {
            status = "Mail opt out";
          }
        } else if (type == SSL) {

        }
      } catch (Exception e) {
        result = 2;
        errorMessage = e;
        e.printStackTrace(System.out);
      }
    } else {
      System.out.println("Notification-> Type not set");
    }
  }


  
  public void notifySystem() throws Exception {
    if (type == SSL) {
      if (System.getProperty("DEBUG") != null) {
        System.out.println("Notification-> SENDING SSL NOTIFICATION");
      }
      SSLMessage thisMessage = new SSLMessage();
      thisMessage.setUrl(host);
      thisMessage.setPort(port);
      thisMessage.setMessage(messageToSend);
      if (context != null) {
        if (context instanceof TActionContext) {
          thisMessage.setKeystoreLocation(
              (String) ((TActionContext) context).getServletContext().getAttribute(
                  "ClientSSLKeystore"));
          thisMessage.setKeystorePassword(
              (String) ((TActionContext) context).getServletContext().getAttribute(
                  "ClientSSLKeystorePassword"));
        }
      }
      result = thisMessage.send();
      if (System.getProperty("DEBUG") != null) {
        System.out.println("Notification->SEND RESULT: " + result);
      }
    }
  }





  
  protected void buildRecord(ResultSet rs) throws SQLException {
	if(System.getProperty("DEBUG")!=null)System.err.println(this.getClass().getName()+".buildRecord");
    id = rs.getInt("notification_id");
    userToNotify = rs.getInt("notify_user");
    module = rs.getString("module");
    itemId = rs.getInt("item_id");
    itemModified = rs.getTimestamp("item_modified");
    attempt = rs.getTimestamp("attempt");
    typeText = rs.getString("notify_type");
    subject = rs.getString("subject");
    messageToSend = rs.getString("message");
    result = rs.getInt("result");
    errorMessage = new Exception(rs.getString("errorMessage"));
  }


  
  public String toString() {

    StringBuffer text = new StringBuffer();
    text.append("==[ NOTIFICATION ]============================").append(lf);
    text.append("User to notify: ").append(userToNotify).append(lf);
    text.append("Module: ").append(module).append(lf);
    text.append("Item Id: ").append(itemId).append(lf);
    text.append("Item Modified: ").append(itemModified).append(lf);
    text.append("Subject: ").append(subject).append(lf);
    text.append("From: ").append(from).append(lf);
    text.append("Message: ").append(messageToSend).append(lf);
    text.append("Type: ").append(type).append(lf);
    text.append("==============================================");
    return text.toString();
  }


  
  public static ArrayList recordList(Connection db) throws SQLException {
    ArrayList records = new ArrayList();
    PreparedStatement pst = db.prepareStatement(
        "SELECT * FROM notification " +
            "WHERE notification_id > -1 ");
    ResultSet rs = pst.executeQuery();
    while (rs.next()) {
      Notification notification = new Notification(rs);
      records.add(notification);
    }
    rs.close();
    pst.close();
    return records;
  }
	public String getReplyMail(){
		return this.replyMail;
	}
	public void setReplyMail(String replyMail){
		this.replyMail=replyMail;
	}
	public String getReplyFax(){
		return this.replyFax;
	}
	public void setReplyFax(String replyFax){
		this.replyFax=replyFax;
	}
	public final static String convertToNumber(String tmp) {
    tmp = tmp.trim();
    StringBuffer sb = new StringBuffer();
    String allowed = "0123456789";
    for (int i = 0; i < tmp.length(); i++) {
      String theChar = tmp.substring(i, i + 1);
      if (allowed.indexOf(theChar) > -1) {
        sb.append(theChar);
      }
      if (i == 0 && theChar.equals("+")) {
        sb.append(theChar);
      }
    }
    return sb.toString();
  }
}
